import ubluetooth as bt
from utime import sleep
from ble_advertising import decode_name, advertising_payload
from hid_services import HIDConst
import _thread


# List of services: https://www.bluetooth.com/specifications/gatt/services/
UUID_HR = bt.UUID(0x180D)
UUID_HID = bt.UUID(0x1812)
UUID_BATTERY = bt.UUID(0x180F)
UUID_DEVICE_INFO = bt.UUID(0x180A)

# REPORT_UUID = bt.UUID(0x2A4D)
# REPORT_MAP_UUID = bt.UUID(0x2A4B)

# Indicate GATT characteristics
# List of characteristics: https://www.bluetooth.com/specifications/gatt/characteristics/
# PROTOCOL_MODE = (bt.UUID(0x2A4E), bt.FLAG_READ | bt.FLAG_NOTIFY,)
# BOOT_INPUT_DEVICE = (bt.UUID(0x2A22), bt.FLAG_READ | bt.FLAG_NOTIFY,)

HR_CHAR = (bt.UUID(0x2A37), bt.FLAG_READ | bt.FLAG_NOTIFY,)
HR_SERVICE = (UUID_HR, (HR_CHAR,),)

HID_READ = (bt.UUID(0x2A4D), bt.FLAG_READ | bt.FLAG_NOTIFY,) # ((bt.UUID(0x2908), 0),)) # 0x2B37
HID_WRITE = (bt.UUID(0x2A4D), bt.FLAG_WRITE,)
HID_SERVICE = (UUID_HID, (HID_READ, HID_WRITE,),)

BATTERY_READ = (bt.UUID(0x2A19), bt.FLAG_READ | bt.FLAG_NOTIFY,)
BATTERY_SERVICE = (UUID_BATTERY, (BATTERY_READ,),)

DEVICE_INFO_READ = (bt.UUID(0x2A50), bt.FLAG_READ | bt.FLAG_NOTIFY,)
DEVICE_INFO_SERVICE = (UUID_DEVICE_INFO, (DEVICE_INFO_READ,),)

SERVICES = (HID_SERVICE, BATTERY_SERVICE, DEVICE_INFO_SERVICE,)
SERVICE_BATTERY = (BATTERY_SERVICE,)
SERVICE_HID = (HID_SERVICE,)
SERVICE_HR = (HR_SERVICE,)


class BLE_HID(object):
	def __init__(self, ble, name="walk_kb"):
		self.__ble = ble
		self.__name = name
		self.__connection = []

		self.__hid_read_handle = None
		self.__hid_write_handle = None
		self.__battery_read_handle = None
		self.__device_info_read_handle = None
		self.__hr_read_handle = None

		self.__payload = advertising_payload(name=self.__name, services=[UUID_HID, UUID_BATTERY, UUID_DEVICE_INFO], appearance=961)

		print("activating ble...")
		self.__ble.active(True)
		print("ble activated")

		self.__ble.irq(self.__irq)

		self.__register_services()
		print("services registed")

		self.___advertise()
	
	def send(self, value=0):
		# b'\x00\x42'
		ba = bytearray(2)
		ba[1]=value
		self.__ble.gatts_notify(self.__connection[0], self.__hid_read_handle, ba)

	def __register_services(self):
		# ((self.__hr_read_handle,),) = self.__ble.gatts_register_services(SERVICE_HR)
		((self.__hid_read_handle, self.__hid_write_handle,), (self.__battery_read_handle,), (self.__device_info_read_handle,),) = self.__ble.gatts_register_services(SERVICES)
		# ((self.__battery_read_handle,),) = self.__ble.gatts_register_services(SERVICE_BATTERY)

	def ___advertise(self):
		print("[{}] advertising...".format(self.__name))

		self.__ble.gap_advertise(100, self.__payload)

	def __irq(self, event, data):
		if event == HIDConst.IRQ_CENTRAL_CONNECT:
			conn_handle, addr_type, addr = data

			self.__connection.append(conn_handle)

			print("central connected, conn_handle: {}, addr_type: {}, addr: {}".format(conn_handle, addr_type, self.__get_bt_mac(addr)))
		elif event == HIDConst.IRQ_CENTRAL_DISCONNECT:
			conn_handle, addr_type, addr = data

			self.__connection.remove(conn_handle)
			
			print("central disconnected, conn_handle: {}, addr_type: {}, addr: {}".format(conn_handle, addr_type, self.__get_bt_mac(addr)))

			self.___advertise()
		else:
			print("event: {}, data: {}".format(event, data))

	def __get_bt_mac(self, value):
		assert isinstance(value, bytes) and len(value) == 6, ValueError("mac address value error")

		return ":".join(['%02X' % byte for byte in value])

forever_loop = True
hid = None

def ble_loop():
	while forever_loop:
		sleep(0.2)

	print("end")	

def main():
	global forever_loop, hid

	init_button()

	ble = bt.BLE()
	hid = BLE_HID(ble)

	while forever_loop:
		sleep(0.2)

	# _thread.start_new_thread(ble_loop, ())

def init_button():
	global hid

	from machine import Pin

	def button_click_cb(timer):
		hid.send(75)

	button = Pin(0, Pin.IN, Pin.PULL_UP)
	button.irq(button_click_cb, Pin.IRQ_RISING)

	print("button initialized")


if __name__ == "__main__":
	try:
		main()
	except KeyboardInterrupt:
		forever_loop = False

		print("\nPRESS CTRL+D TO RESET DEVICE")
